package com.codoon.unova.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

public class BitmapUtil {

	/** 水平方向模糊度 */
	private static float hRadius = 3;
	/** 竖直方向模糊度 */
	private static float vRadius = 3;
	/** 模糊迭代度 */
	private static int iterations = 7;

	/**
	 * 
	 * Function: 将图片转换为圆形图片
	 * 
	 * @param bitmap
	 * @return
	 */
	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		int color = 0xff424242;
		Paint paint = new Paint();
		Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		RectF rectF = new RectF(rect);
		float roundPx = bitmap.getWidth() / 2;

		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		return output;
	}

	/**
	 * 
	 * Function: 图片模糊
	 * 
	 * @param bmp
	 * @return
	 */
	public static Drawable BoxBlurFilter(Bitmap bmp) {

		int width = bmp.getWidth();

		int height = bmp.getHeight();

		int[] inPixels = new int[width * height];

		int[] outPixels = new int[width * height];

		Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

		bmp.getPixels(inPixels, 0, width, 0, 0, width, height);

		for (int i = 0; i < iterations; i++) {

			blur(inPixels, outPixels, width, height, hRadius);

			blur(outPixels, inPixels, height, width, vRadius);

		}

		blurFractional(inPixels, outPixels, width, height, hRadius);

		blurFractional(outPixels, inPixels, height, width, vRadius);

		bitmap.setPixels(inPixels, 0, width, 0, 0, width, height);

		Drawable drawable = new BitmapDrawable(bitmap);

		return drawable;

	}

	public static void blur(int[] in, int[] out, int width, int height,

	float radius) {

		int widthMinus1 = width - 1;

		int r = (int) radius;

		int tableSize = 2 * r + 1;

		int divide[] = new int[256 * tableSize];

		for (int i = 0; i < 256 * tableSize; i++)

			divide[i] = i / tableSize;

		int inIndex = 0;

		for (int y = 0; y < height; y++) {

			int outIndex = y;

			int ta = 0, tr = 0, tg = 0, tb = 0;

			for (int i = -r; i <= r; i++) {

				int rgb = in[inIndex + clamp(i, 0, width - 1)];

				ta += (rgb >> 24) & 0xff;

				tr += (rgb >> 16) & 0xff;

				tg += (rgb >> 8) & 0xff;

				tb += rgb & 0xff;

			}

			for (int x = 0; x < width; x++) {

				out[outIndex] = (divide[ta] << 24) | (divide[tr] << 16)

				| (divide[tg] << 8) | divide[tb];

				int i1 = x + r + 1;

				if (i1 > widthMinus1)

					i1 = widthMinus1;

				int i2 = x - r;

				if (i2 < 0)

					i2 = 0;

				int rgb1 = in[inIndex + i1];

				int rgb2 = in[inIndex + i2];

				ta += ((rgb1 >> 24) & 0xff) - ((rgb2 >> 24) & 0xff);

				tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16;

				tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8;

				tb += (rgb1 & 0xff) - (rgb2 & 0xff);

				outIndex += height;

			}

			inIndex += width;

		}

	}

	public static void blurFractional(int[] in, int[] out, int width,

	int height, float radius) {

		radius -= (int) radius;

		float f = 1.0f / (1 + 2 * radius);

		int inIndex = 0;

		for (int y = 0; y < height; y++) {

			int outIndex = y;

			out[outIndex] = in[0];

			outIndex += height;

			for (int x = 1; x < width - 1; x++) {

				int i = inIndex + x;

				int rgb1 = in[i - 1];

				int rgb2 = in[i];

				int rgb3 = in[i + 1];

				int a1 = (rgb1 >> 24) & 0xff;

				int r1 = (rgb1 >> 16) & 0xff;

				int g1 = (rgb1 >> 8) & 0xff;

				int b1 = rgb1 & 0xff;

				int a2 = (rgb2 >> 24) & 0xff;

				int r2 = (rgb2 >> 16) & 0xff;

				int g2 = (rgb2 >> 8) & 0xff;

				int b2 = rgb2 & 0xff;

				int a3 = (rgb3 >> 24) & 0xff;

				int r3 = (rgb3 >> 16) & 0xff;

				int g3 = (rgb3 >> 8) & 0xff;

				int b3 = rgb3 & 0xff;

				a1 = a2 + (int) ((a1 + a3) * radius);

				r1 = r2 + (int) ((r1 + r3) * radius);

				g1 = g2 + (int) ((g1 + g3) * radius);

				b1 = b2 + (int) ((b1 + b3) * radius);

				a1 *= f;

				r1 *= f;

				g1 *= f;

				b1 *= f;

				out[outIndex] = (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;

				outIndex += height;

			}

			out[outIndex] = in[width - 1];

			inIndex += width;

		}

	}

	public static int clamp(int x, int a, int b) {

		return (x < a) ? a : (x > b) ? b : x;

	}

	/**
	 * 
	 * Function: 使用ifmodified请求头，实现图片的缓存
	 * 
	 * @param context
	 * @param address
	 * @return
	 */
	public Bitmap getBitmap(Context context, String address) {
		Bitmap bitmap = null;
		try {
			URL url = new URL(address);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(3000);
			// 获取当前程序的缓存文件夹位置,在该文件夹创建缓存文件
			File cacheFile = new File(context.getCacheDir(), URLEncoder.encode(address));

			if (cacheFile.exists()) { // 如果存在缓存文件
				conn.setIfModifiedSince(cacheFile.lastModified()); // 设置最后修改时间
			}

			int code = conn.getResponseCode();
			System.out.println(code);
			if (code == 200) { // 响应200代表需要读取网络
				// 从网络读取数据生成字节数组
				byte[] data = parseData(conn.getInputStream()); 
				// 把字节数组解码为Bitmap图片
				bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
				// 把Bitmap图片压缩保存到cacheFile中
				bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(cacheFile));
			} else if (code == 304) { // 响应304代表需要读取缓存
				bitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath()); // 从文件解码为图片
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return bitmap;
	}

	/**
	 * 读取指定输入流中的数据, 返回一个字节数组
	 * 
	 * @param in
	 *            包含数据的输入流
	 * @return 所有数据组成的字节数组
	 */
	public byte[] parseData(InputStream is) {
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len;
			while ((len = is.read(buffer)) != -1)
				baos.write(buffer, 0, len);
			byte[] data = baos.toByteArray();
			return data;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					if (baos != null) {
						try {
							baos.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}

			}

		}
		return null;
	}

}
